#include "Shader.h"

CShader::CShader()
{

}

CShader::~CShader()
{
}

void CShader::AddItem( eItemType type, const char * pName, const char *pValue )
{
	switch ( type )
	{
		case UNIFORM :
			AddUniform( pName, pValue );
			break;
		case ATTRIBUTE :
			AddAttribute( pName, pValue );
			break;
		case VARYING:
			AddVarying( pName, pValue );
			break;
		case  STATMENT:
			AddStatement( pName, pValue );
			break;
		default:
			break;
	}
}

void CShader::AddStatement( const char *pName, const char * pValue )
{
	// It is just a line of statement
	m_listStatement.push_back( pValue );
}

void CShader::AddUniform( const char * pName, const char * pValue )
{
	m_listUniform.push_back("uniform " + std::string(pName) + " " + std::string(pValue) + ";" );
	m_listUniformName.push_back( pValue );
}

void CShader::AddAttribute( const char *pName, const char * pValue )
{
	m_listAttribute.push_back("attribute " + std::string(pName) + " " + std::string(pValue) + ";" );
	m_listAttributeName.push_back( pValue );
}

void CShader::AddVarying( const char *pName, const char * pValue )
{
	m_listVarying.push_back("varying " + std::string(pName) + " " + std::string(pValue) + ";" );
}

void CShader::AddFunction( const char *pName, const char *pValue )
{
	// it is the function method
	m_listFunction.push_back( std::string(pValue) );
}

const char * CShader::GetSource()
{
	m_strSrc.clear();

	// add the head
	m_strSrc = "\
	#ifdef GL_ES\n\
	precision highp float;\n\
	#endif\n";

	ITEMLIST::const_iterator it;
	for( it = m_listAttribute.begin(); it != m_listAttribute.end(); ++it )
	{
		m_strSrc += (*it) + "\n";
	}

	for ( it = m_listUniform.begin(); it != m_listUniform.end(); ++it )
	{
		m_strSrc += (*it) + "\n";
	}

	for ( it = m_listVarying.begin(); it != m_listVarying.end(); ++it )
	{
		m_strSrc += (*it) + "\n";
	}
	
	m_strSrc += "void main(void){\n\t";
	for ( it = m_listStatement.begin(); it != m_listStatement.end(); ++it )
	{
		m_strSrc += (*it) + "\n";
	}

	m_strSrc += "}\n";
	
	return m_strSrc.c_str();
}

FragmentShader::FragmentShader()
{
	AddVarying("vec2", "vTexCoord");
	AddVarying("vec2", "vLightCoord");
	AddUniform("sampler2D", "texture");
	AddUniform("sampler2D", "lightmap");

	AddStatement("", "vec4 diffuseColor = texture2D(texture, vTexCoord)");
	AddStatement("", "vec4 lightColor = texture2D(lightmap, vLightmapCoord)");
	AddStatement("", "gl_FragColor = vec4(diffuseColor.rgb * lightColor.rgb, diffuseColor.a)");

}
FragmentShader::~FragmentShader()
{

}

VertexShader::VertexShader()
{
	AddAttribute( "vec3", "position" );
	AddAttribute( "vec3", "normal" );
	AddAttribute( "vec4", "color" );
	AddAttribute("vec2", "texCoord");
	AddAttribute("vec2", "lightCoord");
	AddVarying("vec2", "vTexCoord");
	AddVarying("vec2", "vLightCoord");
	AddVarying("vec4", "vColor");
	AddUniform("mat4", "view");
	AddUniform("mat4", "projection");
	AddStatement("", "vec3 defPosition = position;");
	AddStatement("", "vec4 worldPosition = view * vec4(defPosition, 1.0 );");
	AddStatement("", "vColor = color; ");
	AddStatement("", "vTexCoord = texCoord;");
	AddStatement("", "vLightCoord = lightCoord;");
	AddStatement("", "gl_Position = projection * worldPosition;");
}

VertexShader::~VertexShader()
{

}

